#include "user_info_request.h"

#include <string>
#include <boost/regex.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include <openssl/md5.h>

#include "base/logging.h"
#include "base/json_escape.h"
#include "im/common/common.h"

// using imserver::UserProfileAdapter;

namespace imserver {
namespace fcgi {

std::string CalculateTempIdSession(int64_t temp_id) {
  static std::string kSessionSalt = "xnp%%l?0$thri9x\r\nxv!66SFqxh3gooa2#D4@8zR34!";
  std::stringstream ss;
  ss << kSessionSalt << temp_id
     << (temp_id * 3 % 119873) << "well,let's_add_more_salt_simida.$94180256";

  unsigned char digest[MD5_DIGEST_LENGTH];
  
  MD5((unsigned char*)ss.str().c_str(), ss.str().size(), (unsigned char*)&digest);

  std::stringstream res;
  for (size_t i = 0; i < MD5_DIGEST_LENGTH; ++i) {
    res << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)digest[i];
  }
  return res.str();
}

void ImBaseRequest::ParseUserIdentity() {
  // 验证登录用户身份
  try {
    qid_ = boost::lexical_cast<int64_t>(GetCookie(IM_QID_COOKIE));
  } catch (boost::bad_lexical_cast&) {}

  if (qid_ > 0) {
    std::string qid_ticket = GetCookie(IM_QID_TICKET_COOKIE);
    if (qid_ticket.empty() || !SessionAdapter::Instance().VerifySession(qid_, qid_ticket, 2)) {
      LOG_WARN("qid verify fail : " << qid_ << " rk=" << qid_ticket);
      qid_ = 0;
    }
  }

  // 验证临时用户身份
  try {
    temp_id_ = boost::lexical_cast<int64_t>(GetCookie(IM_TEMP_ID_COOKIE));
  } catch (boost::bad_lexical_cast&) {}
 
  if (temp_id_ > IM_TEMP_ID_BASE) { 
    std::string temp_id_ticket = GetCookie(IM_TEMP_ID_TICKET_COOKIE);
    if (!boost::starts_with(temp_id_ticket, CalculateTempIdSession(temp_id_))) {
      LOG_WARN("temp_id verify fail : " << temp_id_ << " tk=" << temp_id_ticket);
      temp_id_ = 0;
    } else {
      LOG_DEBUG("temp_id verify ok : " << temp_id_ << " tk=" << temp_id_ticket);
    }
  }
}

std::string ImBaseRequest::ParseCallback() {
  std::string callback = GetQuery("callback");
  static const boost::regex e("[a-zA-Z_][a-zA-Z0-9_.]*");
  if (!callback.empty() && boost::regex_match(callback, e)) {
    return callback;
  }
  static const std::string empty;
  return empty;
}

}
}


